﻿using RpcCacheClient.Interface;
using RpcHelper;
using RpcModel;
using RpcSync.Collect;
using RpcSync.Collect.Model;
using RpcSync.Service.Interface;

namespace RpcSync.Service.ConfigService
{
    [RpcClient.Attr.ClassLifetimeAttr(RpcClient.Attr.ClassLifetimeType.单例)]
    internal class ConfigRefreshService : IConfigRefreshService
    {
        private readonly string _CacheKey = "ConfigUpdateTime";
        private ISysConfigCollect _Config;
        private ICacheController _Cache;
        private IBroadcastService _Broadcast;
        public ConfigRefreshService(ISysConfigCollect config,
            IBroadcastService broadcast,
            ICacheController cache)
        {
            this._Broadcast = broadcast;
            this._Cache = cache;
            this._Config = config;
        }

        public void Refresh()
        {
            Dictionary<string, DateTime> refreshs = _Config.GetToUpdateTime();
            this._FormatTime(refreshs);
            List<string> changes;
            if (this._Cache.TryGet(_CacheKey, out Dictionary<string, DateTime> time))
            {
                changes = _ToChanges(time, refreshs);
            }
            else
            {
                changes = refreshs.Keys.ToList();
            }
            if (changes.Count > 0)
            {
                changes.ForEach(c =>
                {
                    _Refresh(c);
                });
                this._Cache.Set(_CacheKey, refreshs);
            }
        }
        private void _Refresh(string type)
        {
            SysConfigItem item = _Config.Refresh(type);
            BroadcastMsg msg = new BroadcastMsg
            {
                IsExclude = false,
                IsCrossGroup = true,
                IsLimitOnly = false,
                MsgKey = "Rpc_RefreshConfig",
                MsgBody = new SysConfigRefresh { ConfigMd5 = item.Md5 }.ToJson(),
                TypeVal = new string[]
                {
                   type
                }
            };
            _Broadcast.Send(msg, RpcClient.RpcClient.CurrentSource);
        }
        private List<string> _ToChanges(Dictionary<string, DateTime> source, Dictionary<string, DateTime> sets)
        {
            List<string> list = new List<string>(sets.Count);
            string[] one = source.Keys.ToArray();
            string[] two = sets.Keys.ToArray();
            one.ForEach(c =>
            {
                if (!two.IsExists(c))
                {
                    list.Add(c);
                }
            });
            two.ForEach(c =>
            {
                if (!one.IsExists(c) || sets[c] > source[c])
                {
                    list.Add(c);
                }
            });
            return list;
        }

        private void _FormatTime(Dictionary<string, DateTime> dic)
        {
            if (!dic.TryGetValue(string.Empty, out DateTime publicTime))
            {
                return;
            }
            dic.Remove(string.Empty);
            //dic.Add("public", publicTime);
            string[] keys = dic.Keys.OrderBy(a => a).ToArray();
            keys.ForEach(c =>
            {
                if (c != string.Empty && dic[c] < publicTime)
                {
                    dic[c] = publicTime;
                }
            });
        }
    }
}
